/*
 * TSPCostMatrix.cpp
 *
 *  Created on: Jan 23, 2011
 *      Author: santiago
 */

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <assert.h>

#include "TSPCostMatrix.h"

using namespace std;

TSPCostMatrix::TSPCostMatrix(): _node_count(0) {
}

TSPCostMatrix::TSPCostMatrix(const TSPCostMatrix &original): _node_count(original.get_node_count()) {
	_costs.reserve(_node_count);

	vector<double> *destinationNodes;
	for (unsigned int nodeIndex = 0; nodeIndex < _node_count; nodeIndex++) {
		destinationNodes = new vector<double>();
		destinationNodes->reserve(nodeIndex+1);

		for (unsigned int destiantionNodeIndex = 0;
				destiantionNodeIndex < nodeIndex + 1; destiantionNodeIndex++) {

			destinationNodes->push_back(original.get_cost(nodeIndex, destiantionNodeIndex));
		}

		_costs.push_back(*destinationNodes);
		delete destinationNodes;
	}
}

TSPCostMatrix::TSPCostMatrix(unsigned int node_count): _node_count(node_count) {
	_costs.reserve(node_count);

	vector<double> *destinationNodes;
	for (unsigned int nodeIndex = 0; nodeIndex < node_count; nodeIndex++) {
		destinationNodes = new vector<double>();
		destinationNodes->reserve(nodeIndex+1);

		for (unsigned int destiantionNodeIndex = 0;
				destiantionNodeIndex < nodeIndex + 1; destiantionNodeIndex++) {

			destinationNodes->push_back(0.0);
		}

		_costs.push_back(*destinationNodes);
		delete destinationNodes;
	}
}

TSPCostMatrix::~TSPCostMatrix() {
}

TSPCostMatrix& TSPCostMatrix::operator=(const TSPCostMatrix &original) {
	_node_count = original.get_node_count();
	_costs.clear();
	_costs.reserve(_node_count);

	vector<double> *destinationNodes;
	for (unsigned int nodeIndex = 0; nodeIndex < _node_count; nodeIndex++) {
		destinationNodes = new vector<double>();
		destinationNodes->reserve(nodeIndex+1);

		for (unsigned int destiantionNodeIndex = 0;
				destiantionNodeIndex < nodeIndex + 1; destiantionNodeIndex++) {

			destinationNodes->push_back(original.get_cost(nodeIndex, destiantionNodeIndex));
		}

		_costs.push_back(*destinationNodes);
		delete destinationNodes;
	}

	return *this;
}

void TSPCostMatrix::convert_to_matrix(unsigned int node_index_1, unsigned int node_index_2, unsigned int &first_node_index, unsigned int &second_node_index) const {
	if (node_index_1 < node_index_2) {
		first_node_index = node_index_2;
		second_node_index = node_index_1;
	} else {
		first_node_index = node_index_1;
		second_node_index = node_index_2;
	}

	assert(_costs.size() > first_node_index);
	assert(_costs[first_node_index].size() > second_node_index);
}

/*
 * Setea el costo entre dos nodos.
 */
void TSPCostMatrix::set_cost(unsigned int node_index_1, unsigned int node_index_2, double cost) {
	unsigned int first_node_index;
	unsigned int second_node_index;
	convert_to_matrix(node_index_1, node_index_2, first_node_index, second_node_index);

	_costs[first_node_index][second_node_index] = cost;
}

unsigned int TSPCostMatrix::get_node_count() const {
	return _node_count;
}

/*
 * Retorna el costo entre dos nodos.
 */
double TSPCostMatrix::get_cost(unsigned int node_index_1, unsigned int node_index_2) const {
	unsigned int first_node_index;
	unsigned int second_node_index;

	convert_to_matrix(node_index_1, node_index_2, first_node_index, second_node_index);

	return _costs[first_node_index][second_node_index];
}

/*
 * Muestra a stdout los costos entre todos los nodos.
 */
void TSPCostMatrix::show() const {
	puts("=== COST MATRIX ======================");
	for (unsigned int current_node_Id = 0; current_node_Id < _costs.size(); current_node_Id++) {
		for (unsigned int destination_node_Id = 0; destination_node_Id < current_node_Id;
				destination_node_Id++) {

			cout << "(" << current_node_Id << "," << destination_node_Id << ") = " << get_cost(current_node_Id, destination_node_Id) << endl;
		}
		cout << endl;
	}
	puts("======================================");
}
